#include <sys_config.h>
#include <retcode.h>
#include <types.h>
#include <osal/osal.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/sci/sci.h>
#include <bus/dog/dog.h>
#include <hld/hld_dev.h>
#include <hld/pan/pan_dev.h>
#include <hld/pan/pan.h>
#include <hld/pan/pan_key.h>
#include <hld/decv/vdec_driver.h>
#include <hld/deca/deca.h>
#include <api/libtsi/sec_tdt2.h>
#ifndef NEW_DEMO_FRAME
#include <api/libpub29/lib_pub27.h>
#include <api/libpub29/lib_hde.h>
#else
#include <api/libpub/lib_hde.h>
#endif
#include <hld/pan/pan_dev.h>
#include <hld/pan/pan.h>
#include <api/libci/ci_plus.h>

#if (defined(EWS_FUNCTION))
#include <api/libsi/sie_monitor.h>
#endif
#ifdef SUPPORT_VMX
#include <bus/otp/otp.h>
#endif

#include "./platform/board.h"

#include "sys_config.h"
#include "copper_common/system_data.h"
#include "control.h"
#include "key.h"
#include "vkey.h"
#include "win_com.h"
#include "win_signalstatus.h"
#if defined (SUPPORT_VMX) || defined (SUPPORT_VMX_STD)
#ifdef NEW_SELF_TEST_UART_ENABLE
#include "vmx_ap/self_test.h"
#endif
#endif
#define	SIGNAL_PRINTF		PRINTF

//#define DUMP_KEY_CODE

static OSAL_ID INPUT_TASK_ID;

#define 	INPUT_TASK_PRIORITY		OSAL_PRI_NORMAL
#define 	INPUT_TASK_STACKSIZE		0x1000
#define 	INPUT_TASK_QUANTUM		10

#define	IR_KEY_MASK	0xFFFFFFFF
#define	IR_NEC_KEY_MASK	0xFFFF0000

/***************************************************/
/*      ALL kinds of RCU code defintion             */
/***************************************************/
enum signal_flag signal_detect_flag;
UINT8 		upgrade_detect_flag;
UINT32	key_address_mask;
UINT32	key_address;	

pfn_key_notify_callback m_pfn_key_notify;

UINT8 g_rgb_yuv_switch =1, g_rgb_yuv_changed =0;
static UINT16 m_ddplus_dynamic_pid, m_dd_ddplus_changed;
static UINT8 m_rgb_yuv_changing;
static UINT8 m_ci_reset_count;

extern sys_state_t  system_state;
extern UINT8        g_key_task_get_key;
extern UINT32       g_signal_scram_flag;
extern UINT32       g_signal_unlock_flag;
extern UINT8        g_cam_pmt_ok_flag;
extern UINT8        g_cam_pmt_ok_count;
extern UINT8        g_ca_prog_reset_flag;

//extern UINT8 get_fp51_time;
#define KEY_DETECT_INTERVAL     50
#define SIGNAL_DETECT_DELAY_TIMES (300/KEY_DETECT_INTERVAL)///ms
#define DELAY_SIGNAL_DETECT_DELAY_TIMES (SIGNAL_DETECT_DELAY_TIMES*4)
void pvr_monitor_task(void);

void key_set_upgrade_check_flag(UINT8 upgrade_flag)
{
	upgrade_detect_flag = upgrade_flag;
}

static UINT8 set_signal_check_flag = 0;
void key_set_signal_check_flag(enum signal_flag  flag)
{
	signal_detect_flag = flag;
	set_signal_check_flag = 1;
    set_signal_scramble_fake(0);
    g_signal_scram_flag = 0;
    g_signal_unlock_flag = 0;
    g_cam_pmt_ok_count = 0;
    m_ci_reset_count = 0;
    g_ca_prog_reset_flag = 0;
}

pfn_key_notify_callback ap_set_key_notify_proc(pfn_key_notify_callback pfn_notify)
{
    pfn_key_notify_callback old_proc = m_pfn_key_notify;

    m_pfn_key_notify = pfn_notify;

    return old_proc;
}

UINT32 ap_key_msg_code_to_vkey(UINT32 msg_code)
{
	UINT32 vkey;
	ap_hk_to_vk(0, msg_code, &vkey);
    return vkey;
}

BOOL ap_key_map_use_hkey(UINT32 msg_code, PFN_KEY_MAP key_map)
{
	/*If no keymap function,it means the object doesn't process key message */
	if(key_map == NULL)
		return FALSE;

	VACTION action = VACT_PASS;
	UINT32	vkey = V_KEY_NULL;
	UINT32	i = 0;

	do
	{
		i = ap_hk_to_vk(i, msg_code, &vkey);
		if(vkey == V_KEY_NULL)
            break;
		action = key_map(NULL, vkey);
	} while (action == VACT_PASS);

    return (action != VACT_PASS);
}


extern UINT8   led_data_len;
UINT8 key_device_init()
{
	UINT8	b;
	INT32	retVal;


#if 0
	g_pan_dev = (struct pan_device *) dev_get_by_id(HLD_DEV_TYPE_PAN, 0);
	if(NULL == g_pan_dev)
	{
		PRINTF("dev_get_by_name failed\n");
		return FALSE;
	}

	retVal = pan_open(g_pan_dev);
	if(retVal!=SUCCESS)
	{
		PRINTF("pan_open failed retVal=%d\n",retVal);
		return FALSE;
	}
	pan_display(g_pan_dev," on ", 4);
#endif	
    if (g_pan_dev == NULL)
        return FALSE;

	led_data_len = g_pan_dev->led_num;

	PRINTF("---------UIKeyInit() ,led display ----\n");
	return TRUE;
}


BOOL key_get_key(struct pan_key *key_struct, UINT32 timeout)
{
	UINT32		controlMsgCode;
	BOOL 			b_valid_key = FALSE;
	struct pan_key *	pan_key;
	pan_key = pan_get_key(g_pan_dev,timeout);
    
#ifdef SFU_TEST_SUPPORT	
	if(SFUTestingIsTurnOn())
		pan_key = NULL;
#endif
	if (pan_key == NULL) 
		return FALSE;
		
	MEMCPY(key_struct, pan_key, sizeof(struct pan_key));
	if(PAN_KEY_INVALID == key_struct->code)
	{
		return FALSE;
	}
	else if(PAN_KEY_TYPE_REMOTE == key_struct->type)
	{
		//Martin@20150128
		if(key_struct->state == 1)
		{
		    libc_printf("GET key = 0x%08x\n", key_struct->code);
#ifdef AUTOMATIC_STANDBY//Martin@20150519_Auto standby
    ap_set_access_active(TRUE);	
    if(get_automatic_windows_state())
    {
        return FALSE;
    }
#endif//End---- Martin
		}
	}


	return TRUE;
}

extern UINT8 play_chan_nim_busy;

void key_check_signal_status(void)
{
    UINT16 level = 0;
    UINT16 level_cur = 0;
	UINT8 quality,lock, lock_ano, quality_cur;
#ifdef DISPLAY_SIGNAL_QUALITY_EXT
	static UINT16 level_pre = 0;
	static UINT8 quality_pre = 0;
#else
	static UINT16 level_pre = 0;
	static UINT8 quality_pre = 0;
#endif
	UINT32 msgcode,cur_ber;
	static UINT32 delay_time = 0,wait_time = DELAY_SIGNAL_DETECT_DELAY_TIMES;
	struct nim_device* nim_dev, *nim_another;
	static BOOL reset_status = FALSE;
	SYSTEM_DATA *pSys_data = sys_data_get();
	
	/* Signal detect */
  	if(g_tuner_num == 1)
		cur_tuner_idx = 0;

	if(cur_tuner_idx == 0)
	{
		nim_dev = g_nim_dev;
		nim_another = g_nim_dev2;
	}
	else
	{
		nim_dev = g_nim_dev2;	
		nim_another = g_nim_dev;
	}
	
	//nim_get_lock(nim_dev, &lock);

	delay_time ++;
		
	if(SIGNAL_CHECK_PAUSE == signal_detect_flag)
	{
		osal_task_sleep(10);
		return;
	}
	else if(SIGNAL_CHECK_RESET == signal_detect_flag)
	{
		//signal_detect_flag = SIGNAL_CHECK_NORMAL;
		//wait_time = DELAY_SIGNAL_DETECT_DELAY_TIMES;
		//delay_time = 0;
		if(set_signal_check_flag)
		{
			wait_time = DELAY_SIGNAL_DETECT_DELAY_TIMES;
			delay_time = 0;
		}
	}
	
	if(set_signal_check_flag)
		set_signal_check_flag = 0;
	
	if(delay_time == wait_time)
	{
		if(wait_time == DELAY_SIGNAL_DETECT_DELAY_TIMES)
			signal_detect_flag = SIGNAL_CHECK_NORMAL;
		
		nim_get_lock(nim_dev, &lock);
#ifdef _S3281_		
		nim_get_AGC(nim_dev, &level_cur);
#endif		
		nim_get_SNR(nim_dev, &quality_cur);
		//nim_get_BER(nim_dev, &cur_ber);
		if(NULL != nim_dev->do_ioctl)
		{
          nim_dev->do_ioctl(nim_dev, NIM_DRIVER_GET_AGC, (UINT32)&level_cur);
          nim_dev->do_ioctl(nim_dev, NIM_DRIVER_GET_BER, (UINT32)&cur_ber);
		}
		if((lock) && (pSys_data->ber_printf))
			libc_printf("Current BER is %d 10e-8\n",cur_ber);//NIM_PRINTF( "current BER is  %d /1000000\n", ber_value);

		level = (level_cur + level_pre)/2;
		quality = (quality_cur + quality_pre)/2;
		level_pre = level_cur;
		quality_pre = quality_cur;


		dem_signal_to_display(lock,&level,&quality);
		msgcode =(cur_tuner_idx<<24) + (level<<16) + (quality<<8) + lock;
		ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SIGNAL, msgcode, FALSE);
		
		if(play_chan_nim_busy)
		{
			win_signal_set_level_quality(0,0,0);
			lock = 0;
		}
		else
			win_signal_set_level_quality(level,quality,lock);

#ifdef SHOW_TWO_TUNER_LOCK_STATUS
		if(g_tuner_num == 2)
		{
			nim_get_lock(nim_another, &lock_ano);
			if(nim_dev == g_nim_dev)
			{
				key_pan_display_lock(lock); 		// first tuner lock status
				key_pan_display_lock2(lock_ano); 	//second tuner lock status
			}
			else
			{
				key_pan_display_lock(lock_ano);		// first tuner lock status
				key_pan_display_lock2(lock);		//second tuner lock status
			}				
		}
		else
		{
			key_pan_display_lock(lock);
		}
#else

		key_pan_display_lock(lock);
#endif

		wait_time = SIGNAL_DETECT_DELAY_TIMES;   
		delay_time = 0;

#ifndef _BUILD_OTA_E_

		// when the signal is missed, try to reset the diseqc and qpsk.
		static UINT32 unlock_times = 0;
		static UINT32 unlock_start_tick = 0;

        #ifdef _S3281_
        static UINT32 first_reset = 0;
        if(!lock && unlock_times > 2)
        {            
            if(first_reset == 0)
            {
                first_reset ++;
                wincom_reset_nim();
            }
        }
        #endif

		if(unlock_times == 0)
			unlock_start_tick = osal_get_tick();

		if(lock)
		{
			unlock_times = 0;
		}
		else
		{
			unlock_times++;
		}
		if(unlock_times > 14)
		{
			unlock_times = 0;
			//libc_printf("reset tick = %d(ms)\n", osal_get_tick() - unlock_start_tick);
#ifndef NEW_DEMO_FRAME
			if(system_state == SYS_STATE_NORMAL && get_cc_crnt_state()!=0)
			{
				//libc_printf("reset diseqc and qpsk\n");
				cc_reset_diseqc(FALSE);
				cc_reset_qpsk(FALSE);
			}
#else
			if(system_state == SYS_STATE_NORMAL)
			{
				//libc_printf("reset diseqc and qpsk\n");
				wincom_reset_nim();
			}

#endif
		}
#endif	

	}
}

extern UINT32 app_uart_id;
UINT32 key_monitor_com()
{
	UINT16 i=0;
	UINT8 ch = 0xff;
#ifdef _REMOVE_STRING_	
	UINT8 *comtest_command = " ";
	UINT8 *apptest_command = " ";
#else
#if defined(SUPPORT_VMX_STD) || defined(SUPPORT_VMX)
	UINT8 *comtest_command = "vmxtest";
#else
	UINT8 *comtest_command = "comtest";
#endif
	UINT8 *apptest_command = "APP  init ok";
#endif	
	INT32 comtest_command_len = STRLEN(comtest_command) - 1;
	INT32 apptest_command_len = STRLEN(apptest_command) - 1;
	UINT8 sync = 0;

#if defined (SUPPORT_VMX) || defined (SUPPORT_VMX_STD)
#ifdef NEW_SELF_TEST_UART_ENABLE
	extern BOOL is_self_test_mode_activate;
	if(is_self_test_mode_activate == TRUE)
	{
		self_test_uart_main();
	}	
#endif
#endif

	i = 0;
	if(UPGRADE_CHECK_HOST & upgrade_detect_flag)
	{
		while(sci_read_tm(app_uart_id, &ch, 10)==SUCCESS)
		{
			if(apptest_command[i]==ch)
			{
				i++;
				if(i>apptest_command_len)
				{
					//system_state = SYS_STATE_UPGRAGE_HOST;
					return 1;
				}
			}
		}
	}

#ifndef _CAS9_CA_ENABLE_
	if(UPGRADE_CHECK_SLAVE & upgrade_detect_flag)
#endif	
	{
		i = 0;
        UINT32 timeout = 1000;
		while(sci_read_tm(app_uart_id,&ch,timeout)==SUCCESS)
		{
			if (i<=comtest_command_len && comtest_command[i] == ch)
			{
			    timeout = 1000*100;
				sci_write(app_uart_id,ch);
				i++ ;
				if (i > comtest_command_len)	/* Is a comtest command string, wait for upgrade */
				{
				    //system_state = SYS_STATE_UPGRAGE_SLAVE;
                    //power_off_process();
					//power_on_process();

					#ifdef SUPPORT_VMX
					if(sci_read_tm(app_uart_id,&ch,timeout)==SUCCESS)
					{
						switch(ch)
						{
							case '1':
								vmx_cas_bc_lock();
								if( 0 != BC_CheckNSc())
								{
									vmx_cas_bc_unlock();
									sci_write(app_uart_id,ch);
									return 2;
								}
								vmx_cas_bc_unlock();
								break;

							case '2':
								{
									UINT32 ejtag_disable = 0;

									otp_init(NULL);
									otp_read(0x3*4, &ejtag_disable, 4);

									if( 0 == (ejtag_disable&(1<<0)) )
									{
										sci_write(app_uart_id,ch);
										return 2;
									}
								}
								break;

							case '3':
								{
									sci_write(app_uart_id,ch);
									return 2;
								}
								break;

							case '4':
							#if 0
								{
									UINT32 uart_fuse = 0;
								
									otp_init(NULL);
								
									otp_read(0x3*4, &uart_fuse, 4);
									
									if( 0 == (uart_fuse&(1<<12)) )
									{
										sci_write(app_uart_id,ch);
										return 2;
									}	
								}
							#endif
								{
									UINT32 addr, len,chid;
									UINT8 *flash_data;	
									CHUNK_HEADER chuck_hdr;	
	
									struct sto_device *flash_dev_deattach = (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0);

									//SN chunk
									chid = 0x20DF0100;	
									if(sto_get_chunk_header(chid,&chuck_hdr)) 
									{
										addr =  (UINT32)sto_chunk_goto(&chid,0xFFFFFFFF,1);//chunk addr
										len = CHUNK_HEADER_SIZE;
		
										flash_data = MALLOC(4);
										MEMSET(flash_data, 0, 4);

										//get original data from flash
										sto_get_data(flash_dev_deattach, flash_data, addr+len+112, 4);
		
										if( (UINT32)0xFFFFFFFF == fetch_long(flash_data) )
										{
											sci_write(app_uart_id,ch);
											return 2;
										}	
										FREE(flash_data);
										flash_data = NULL;
									}
								
								}	
								break;	

							default:
								break;
						}
					}
					#else
					return 2;
					#endif
				}
			} 
            else
                break;
	    }
	}

	return 0;
}

static enum VDEC_PIC_STATUS m_vdec_status;
static UINT32 m_tick_of_last_nonnormal_status; /*Add for avoid EXIT message send out*/

static UINT32 m_vdec_pic_no_show_time, m_vdec_pic_no_show_flag;
static UINT32 m_vdec_display_index, m_vdec_picture_freeze_flag, m_vdec_picture_freeze_time;
static UINT8  m_vdec_status_checking;
static UINT8  m_dmx0_scramble;
static UINT32 m_dmx0_scramble_start_time;

UINT32 key_check_picture_status(void)
{
	struct VDec_StatusInfo CurStatus;
    enum VDEC_PIC_STATUS vdec_status;
    UINT8 scramble;

    m_vdec_status_checking = 1;

#ifdef CI_SUPPORT
    if (win_ci_enquiry_dlg_show())
        scramble = 0;
    else
#endif	
	{
        scramble = api_is_stream_scrambled();
	}

    if (m_dmx0_scramble != scramble)
    {
        m_dmx0_scramble = scramble;
        m_dmx0_scramble_start_time = osal_get_tick();
    }
    else
    {
        if (m_dmx0_scramble_start_time == 0)
            m_dmx0_scramble_start_time = osal_get_tick();
    }

    vdec_io_control(get_selected_decoder(), VDEC_IO_GET_STATUS, (UINT32)&CurStatus);

    if (!CurStatus.uFirstPicShowed)
    {
        vdec_status = VDEC_PIC_NO_SHOW;
        m_vdec_display_index = 0;
        if (m_vdec_pic_no_show_flag == 0)
        {
            m_vdec_pic_no_show_time = osal_get_tick();
            m_vdec_pic_no_show_flag = 1;
        }
        else
        {
            if (CurStatus.uCurStatus != VDEC_DECODING || CurStatus.display_frm == FALSE
#ifdef CI_SUPPORT				
				|| win_ci_enquiry_dlg_show()
#endif				
				)
                m_vdec_pic_no_show_time = osal_get_tick();
        }
#if 0
        else
        {
            if (osal_get_tick() >= (m_vdec_pic_no_show_time + 10000))
            {
                if (api_is_stream_scrambled())
                {
                    DBG_STR("reset pvr player 2");
                    cc_tsg_ci_slot_switch(FALSE);
                    ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
                }
                m_vdec_pic_no_show_time = osal_get_tick();
            }
        }
#endif
    }
    else
    {
        vdec_status = VDEC_PIC_NORMAL;
        m_vdec_pic_no_show_flag = 0;
        if (m_vdec_display_index == 0)
        {
            m_vdec_display_index = CurStatus.display_idx;
            m_vdec_picture_freeze_flag = 0;
        }
        else
        {
            if (m_vdec_display_index == CurStatus.display_idx)
            {
                vdec_status = VDEC_PIC_FREEZE;
                if (m_vdec_picture_freeze_flag == 0)
                {
                    m_vdec_picture_freeze_time = osal_get_tick();
                    m_vdec_picture_freeze_flag = 1;
                }
                else
                {
                    if (CurStatus.uCurStatus != VDEC_DECODING || CurStatus.display_frm == FALSE
#ifdef CI_SUPPORT						
						|| win_ci_enquiry_dlg_show()
#endif						
						)
                        m_vdec_picture_freeze_time = osal_get_tick();
                }
#if 0
                else
                {
                    if (osal_get_tick() >= (m_vdec_picture_freeze_time + 5000))
                    {
                        // picture freeze for 5 sec
                        //DBG_STR("reset pvr player 3");
                        //cc_tsg_ci_slot_switch(FALSE);
                        //ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
                        m_vdec_picture_freeze_time = osal_get_tick();
                    }
                }
#endif
            }
            else
            {
                m_vdec_picture_freeze_flag = 0;
                m_vdec_picture_freeze_time = 0;
                m_vdec_display_index = CurStatus.display_idx;
            }
        }
        if ((m_vdec_status == VDEC_PIC_NO_SHOW || m_vdec_status == VDEC_PIC_FREEZE) && (vdec_status == VDEC_PIC_NORMAL))
        {
#ifdef CI_SUPPORT
			/* Add this code-segment for two reason:
			 * 1. Send Eixt message because, CAM pop up menu: no access, but video comeout 
			 *    just a few moment, however, the menu didn't close.
			 * 2. We close menu for reason1, but it close CAM software update menu when video 
			 *    freeze slightly. So add one condition to avoid Exit message send out in this
			 *    situation.
			 */
			UINT32 c_tick;
			c_tick = osal_get_tick();
			if (m_vdec_status==VDEC_PIC_NO_SHOW)
				m_tick_of_last_nonnormal_status = 0;
            if (win_ci_info_on_screen() 
				&& (c_tick-m_tick_of_last_nonnormal_status)>1000 /* Don't send Exit msg if video just freeze slightly*/
				)
            {
                ap_send_msg(CTRL_MSG_SUBTYPE_KEY_UI, V_KEY_EXIT, FALSE);
            }
#endif			
        }
        else
        {
    		if (AUDIO_TYPE_TEST(m_ddplus_dynamic_pid, AC3_DES_EXIST)
                || AUDIO_TYPE_TEST(m_ddplus_dynamic_pid, EAC3_DES_EXIST)
                )
    		{
                UINT32 audio_str_type = 0;
                RET_CODE ret_code = RET_FAILURE;
                
                ret_code = deca_io_control(g_deca_dev, DECA_GET_STR_TYPE, (UINT32)&audio_str_type);

                if (ret_code == RET_SUCCESS)
                {
                    if ((audio_str_type == AUDIO_EC3) && AUDIO_TYPE_TEST(m_ddplus_dynamic_pid, AC3_DES_EXIST))
                    {
                        m_ddplus_dynamic_pid = (m_ddplus_dynamic_pid & 0x1fff) | EAC3_DES_EXIST;
                        m_dd_ddplus_changed = 1;
                		ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_AUDIO_TYPE_UPDATE,
                			m_ddplus_dynamic_pid, 0);
                    }
                    else if ((audio_str_type == AUDIO_AC3) && AUDIO_TYPE_TEST(m_ddplus_dynamic_pid, EAC3_DES_EXIST))
                    {
                        m_ddplus_dynamic_pid = (m_ddplus_dynamic_pid & 0x1fff) | AC3_DES_EXIST;
                        m_dd_ddplus_changed = 1;
                		ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_AUDIO_TYPE_UPDATE,
                			m_ddplus_dynamic_pid, 0);
                    }
                }
    		}
            else
            {
                m_dd_ddplus_changed = 0;
            }
        }
    }
    m_vdec_status = vdec_status;
	m_tick_of_last_nonnormal_status = osal_get_tick();
    m_vdec_status_checking = 0;
    return 0;
}

enum VDEC_PIC_STATUS key_get_video_status(UINT32 *start_time)
{
    while (m_vdec_status_checking)
    {
        osal_task_sleep(10);
    }
    enum VDEC_PIC_STATUS vdec_status = m_vdec_status;

    if (start_time)
    {
        if (vdec_status == VDEC_PIC_FREEZE)
            *start_time = m_vdec_picture_freeze_time;
        else if (vdec_status == VDEC_PIC_NO_SHOW)
            *start_time = m_vdec_pic_no_show_time;
    }
    return vdec_status;
}

void key_update_video_status_start_time(void)
{
    while (m_vdec_status_checking)
    {
        osal_task_sleep(10);
    }

    if (m_vdec_status == VDEC_PIC_FREEZE)
        m_vdec_picture_freeze_time = osal_get_tick();
    else if (m_vdec_status == VDEC_PIC_NO_SHOW)
        m_vdec_pic_no_show_time = osal_get_tick();

    g_cam_pmt_ok_flag = 0;
    g_cam_pmt_ok_count = 0;
}

BOOL key_get_dmx0_scramble(UINT32 *start_time)
{
    while (m_vdec_status_checking)
    {
        osal_task_sleep(10);
    }
    if (start_time)
    {
        *start_time = m_dmx0_scramble_start_time;
    }
    return m_dmx0_scramble;
}

void key_check_ddplus_prog()
{
    /*fake-scrable*/
	UINT16 chan_idx;
	P_NODE p_node;

    sys_data_get_cur_group_channel(&chan_idx, sys_data_get_cur_chan_mode());
    get_prog_at(chan_idx, &p_node);

	UINT32 cur_audio = (p_node.cur_audio >= p_node.audio_count) ? 0 : p_node.cur_audio;
    UINT16 audio_id = p_node.audio_pid[cur_audio];
	if ((AUDIO_TYPE_TEST(audio_id, AC3_DES_EXIST)
        || AUDIO_TYPE_TEST(audio_id, EAC3_DES_EXIST))         
        )
	{
        UINT32 audio_str_type = 0;
        RET_CODE ret_code = RET_FAILURE;
        //if ((audio_id & 0x1fff) != (m_ddplus_dynamic_pid & 0x1fff))
        {
            m_ddplus_dynamic_pid = audio_id;
        }
	}
    else
	{
        m_ddplus_dynamic_pid = 0;
	}
}

#ifndef _BUILD_OTA_E_
#ifdef CI_SLOT_DYNAMIC_DETECT
void key_check_ca_prog(UINT8 cam_pmt_ok)
{
    /*fake-scrable*/
	signal_lock_status lock_flag;
	signal_scramble_status scramble_flag;
	signal_lnbshort_status lnbshort_flag;    
	signal_parentlock_status parrentlock_flag;
	UINT16 chan_idx;
	P_NODE p_node;
	struct VDec_StatusInfo CurStatus;
    extern UINT32 prog_end_time_tick;
    extern UINT32 prog_start_time_tick;
    extern ScreenBackState_t screen_back_state;

    UINT32 pic_time = 0, scramble_time = 0;
    UINT32 cur_time = osal_get_tick();
    enum VDEC_PIC_STATUS pic_status = key_get_video_status(&pic_time);
    UINT8 scramble = key_get_dmx0_scramble(&scramble_time);

    extern BOOL freeze_for_pvr;
#ifdef DVR_PVR_SUPPORT2
	if (cam_pmt_ok && !api_pvr_is_live_playing())
	{
        if (scramble && cur_time >= (scramble_time + 1000))
        {
            //libc_printf("reset pvr player because scrambled\n");
            ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
            g_cam_pmt_ok_flag = 0;
            g_cam_pmt_ok_count = 0;
        }
        return;
    }
#endif

    sys_data_get_cur_group_channel(&chan_idx, sys_data_get_cur_chan_mode());
    get_prog_at(chan_idx, &p_node);
    prog_end_time_tick = osal_get_tick();
    static UINT32 m_my_tick;

	UINT32 cur_audio = (p_node.cur_audio >= p_node.audio_count) ? 0 : p_node.cur_audio;
	m_ddplus_dynamic_pid = p_node.audio_pid[cur_audio];
	if (!AUDIO_TYPE_TEST(m_ddplus_dynamic_pid, AC3_DES_EXIST|EAC3_DES_EXIST))
        m_ddplus_dynamic_pid = 0;

    if (m_my_tick == 0)
        m_my_tick = prog_end_time_tick;
#if(!defined CC_USE_TSG_PLAYER && defined CI_SLOT_DYNAMIC_DETECT)
	cc_tsg_ci_slot_task_proc();
#endif
    
    /* for fake-scramble prog */
    if  ((p_node.ca_mode) && api_is_playing_tv())
    {
        GetSignalStatus(&lock_flag, &scramble_flag,&lnbshort_flag, NULL); 
        if((lock_flag == SIGNAL_STATUS_LOCK) && (scramble_flag == SIGNAL_STATUS_UNSCRAMBLED)
            && prog_start_time_tick && (prog_end_time_tick > (prog_start_time_tick + 3000)) 
#ifdef DVR_PVR_SUPPORT
	        && api_pvr_is_live_playing() && !freeze_for_pvr
#endif
	        )
        {
            if (pic_status == VDEC_PIC_NO_SHOW || pic_status == VDEC_PIC_FREEZE)
            {
                if (cur_time >= (pic_time + 6000))
                {
                    if (scramble && cur_time >= (scramble_time + 300))
                    {
                        //libc_printf("normal play no pic and scrambled\n");
                        ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
                        key_update_video_status_start_time();
                    }
                    else if (!scramble && cur_time >= (scramble_time + 5000))
                    {
#ifdef CI_SUPPORT
                        //libc_printf("normal play no pic and not scramble\n");
	                    if (api_ci_attached() 
#ifdef DVR_VR_SUPPORT
						&& cc_tsg_task_is_running()
#endif
				)
	                    {
                            if (m_ci_reset_count < 3)
                            {
#ifdef DVR_PVR_SUPPORT
                                cc_tsg_ci_slot_switch(FALSE);
#endif
                                ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
                                m_ci_reset_count++;
                            }
                            else
                            {
#ifdef DVR_PVR_SUPPORT
                                cc_tsg_ci_slot_switch(FALSE);
#endif
                                ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 3, FALSE);
                            }
	                    }
                        else
#endif							
	                    {
                            ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 3, FALSE);
	                    }
                        key_update_video_status_start_time();
                    }
                }
            }
            else if (pic_status == VDEC_PIC_NORMAL)
            {
                m_ci_reset_count = 0;
#ifdef CI_SUPPORT
	            if (api_ci_attached() == FALSE)
                {
#endif
                    set_signal_scramble_fake(1);
                    if (GetSignalStatausShow())
                    {
                        //ShowSignalStatusOSDOnOff(0);
                        ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN,0,FALSE);
                    }
#ifdef CI_SUPPORT
	            }
#endif
            }
        }
        else if((lock_flag == SIGNAL_STATUS_LOCK) && (scramble_flag == SIGNAL_STATUS_SCRAMBLED)
#ifdef DVR_PVR_SUPPORT
	        && api_pvr_is_live_playing() && !freeze_for_pvr
#endif
#ifdef CI_SUPPORT
	        && (api_ci_attached())
#endif
	        )
        {
#ifdef 	CC_USE_TSG_PLAYER		
            if (cam_pmt_ok)
            {
                if (g_cam_pmt_ok_count)
                {
                    if (pic_status == VDEC_PIC_NO_SHOW || pic_status == VDEC_PIC_FREEZE)
                    {
					#ifdef CI_SUPPORT
                        if (cur_time >= (pic_time + 1000))
                        {
                            if (scramble && cur_time >= (scramble_time + 200)
#ifdef DVR_PVR_SUPPORT
					&& cc_tsg_task_is_running()
#endif
				)
                            {
#ifdef DVR_PVR_SUPPORT
                                if (!api_pvr_is_recording_cur_prog() || g_ca_prog_reset_flag < 8)
#endif
                                {
                                    //libc_printf("reset normal player because scrambled %d\n", cur_time);
#ifdef DVR_PVR_SUPPORT
                                    if (g_ca_prog_reset_flag >= 1)
                                        cc_tsg_ci_slot_switch(TRUE);
#endif
                                    ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
                                }
                                g_cam_pmt_ok_count = 0;
                                g_cam_pmt_ok_flag = 0;
                                return;
                            }
                            else if (!scramble && cur_time >= (scramble_time + 3000))
                            {
                                g_cam_pmt_ok_count = 0;
                                g_cam_pmt_ok_flag = 0;
                                return;
                            }
                        }
					#endif
                    }
                }
            }
#endif			
            if (pic_status == VDEC_PIC_NO_SHOW || pic_status == VDEC_PIC_FREEZE)
            {
                if (cur_time >= (pic_time + 5000))
                {
                    if (scramble && cur_time >= (scramble_time + 5000))
                    {
#ifdef DVR_PVR_SUPPORT
                        if (cc_tsg_ci_slot_switch(FALSE))
#endif
                        {
                            libc_printf("normal play no pic and scrambled\n");
                            ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_SCRIMBLE_SIGN, 2, FALSE);
                        }
                        key_update_video_status_start_time();
                    }
                }
            }

        }
    }
}
#endif
#endif

BOOL key_check_ddplus_stream_changed(UINT16 *p_audio_pid)
{
    if (m_ddplus_dynamic_pid && m_dd_ddplus_changed)
    {
        if ((*p_audio_pid & 0x1fff) == (m_ddplus_dynamic_pid & 0x1fff))
        {
            *p_audio_pid = m_ddplus_dynamic_pid;
            libc_printf("DD+ audio type changed: 0x%04x\n", m_ddplus_dynamic_pid);
            m_dd_ddplus_changed = 0;
            return TRUE;
        }
        m_dd_ddplus_changed = 0;
    }

    return FALSE;
}


extern 		app_disable_while_ci_upgrade;

//#ifdef SUPPORT_CAS9
 #if defined( SUPPORT_CAS9) ||defined (SUPPORT_CAS7)

#include <hld/dmx/dmx.h>
#include <api/libcas/mcas.h>
 #if defined( SUPPORT_CAS9) 
#include "conax_ap/win_ca_mmi.h"
#endif
 #if defined (SUPPORT_CAS7)
 #include "conax_ap7/win_ca_mmi.h"
 #endif

extern BOOL mmi_new_msg;
UINT8 mmi_count=0;
extern CONTAINER g_win_popup;
extern BOOL mmipopup_is_closed;
void key_check_mmi()
{
	struct VDec_StatusInfo CurStatus;
	static UINT32 mmi_tick;
	UINT32 duration;
	UINT32 set_duration = 0;
	UINT32 vde_dipy_idx ;
	UINT8 av_ok = 0,i,av_try;
	
	if(get_mmi_showed()!=1&&get_mmi_showed()!=6)
		return;
	
	if(mmi_new_msg)
	{
		mmi_new_msg = FALSE;
		mmi_tick = osal_get_tick();
	}

	duration = osal_get_tick() - mmi_tick;
	if(get_mmi_showed()==1)
		set_duration=3000;//6000;
	else if(get_mmi_showed()==6)
		set_duration=300;
    struct vdec_device * vdec_handle = get_selected_decoder();
			
	if(duration>=set_duration)
	{
		if(ca_is_card_inited()== FALSE)
		{
        vdec_start(vdec_handle);   //fixed bug:can play unscramble stream when pull out cart in scramble stream.
		}
        vdec_io_control(vdec_handle, VDEC_IO_GET_STATUS, (UINT32)&CurStatus);
		if(CurStatus.uFirstPicShowed==TRUE)
		{	
            //libc_printf("2\n");
			av_try=3;
			for(i=0;i<=av_try;i++)
			{
				vde_dipy_idx = CurStatus.display_idx;
					
				osal_task_sleep(200);
		        vdec_io_control(vdec_handle, VDEC_IO_GET_STATUS, (UINT32)&CurStatus);

				if(vde_dipy_idx == CurStatus.display_idx)
					break;
			}
			if(i>av_try)
				av_ok=1;
		}
		if(av_ok==1)
		{
            //libc_printf("3\n");
			if(get_mmi_showed() == 1)
			{
				MMI_PRINTF("video ok, MCAS_DISP_CARD_IN\n");
				ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, MCAS_DISP_CARD_IN<<16, FALSE);
			}
			else if(get_mmi_showed() == 6)
			{
				MMI_PRINTF("video ok, MCAS_DISP_NO_ACCESS_CLR\n");
				ap_send_msg(CTRL_MSG_SUBTYPE_STATUS_MCAS, MCAS_DISP_NO_ACCESS_CLR<<16, FALSE);			
			}
		}
	/*	else
			//if(0)
					mmipopup_is_closed=FALSE;

				}
			}
		}*/
	}
}

#endif


#if(defined(MULTI_CAS) && defined(SUPPORT_CAS_A))
static BOOL abel_key_exist = FALSE;
BOOL abel_key_existed()
{
	return abel_key_exist;
}

void abel_key_is_existed()
{
	abel_key_exist = TRUE;
}

UINT32 abel_upgrade_monitor_com()
{
	UINT8 i;
	UINT8 ch = 0xff;
	UINT8 *comtest_command = "sertest"; //"comtest"
	INT32 comtest_command_len = STRLEN(comtest_command) - 1;

	i = 0;
	UINT32 timeout = 1000;
	while (sci_read_tm(SCI_FOR_RS232, &ch, timeout) == SUCCESS)
	{
		if (i <= comtest_command_len && comtest_command[i] == ch)
		{
			timeout = 1000 * 100;
			sci_write(SCI_FOR_RS232, ch);
			i++;
			if (i > comtest_command_len)
			 /* Is a comtest command string, wait for upgrade */
			{
				return 1;
			}
		}
		else
			break;
	}

	return 0;
}
#endif

#if(defined(MULTI_CAS) && defined(SUPPORT_CAS_A))
static BOOL abel_upg_send = FALSE;
#endif


static void key_task()
{
	UINT32	msg_code;
	struct pan_key key_struct;
    UINT32  ret;

	signal_detect_flag = SIGNAL_CHECK_RESET;
	key_device_init();
	while(1)
	{
		osal_task_sleep(KEY_DETECT_INTERVAL);
        if(system_state == SYS_STATE_INITIALIZING 
            || system_state == SYS_STATE_POWER_OFF
            || system_state == SYS_STATE_UPGRAGE_HOST)
            continue;

#if(defined(MULTI_CAS) && defined(SUPPORT_CAS_A))
		/* Host software upgrade detecting. */
		if(abel_key_existed() == FALSE && abel_upg_send == FALSE)
		{
			ret = abel_upgrade_monitor_com();
			if (ret == 1)
			{
				ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPGRADE_SLAVE, 0, TRUE);
				abel_upg_send = TRUE;
				
			}
		}
#endif

		
#ifdef SFU_TEST_SUPPORT	
		if(SFUTestingIsTurnOn())
		{
			osal_task_sleep(10);
			continue;
		}
#endif	



		/* Host software upgrade detecting. */
#if(defined(MULTI_CAS) && defined(SUPPORT_CAS_A))
		if(abel_key_existed() == TRUE)
		{
			ret = key_monitor_com();
			if(ret == 1 || ret==2)
			{
				if(ret == 1)
#ifdef UPGRADE_HOST_MONITOR			
					ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPGRADE, 0, TRUE);
#else
					;
#endif
				else
					ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPGRADE_SLAVE, 0, TRUE);
			}
		}
#else /* else of defined(MULTI_CAS) && defined(SUPPORT_CAS_A) */

#if !defined(FPGA_TEST)// && (SYS_MAIN_BOARD != BOARD_SB_S3602F_QFP_01V01)
		/* Host software upgrade detecting. */
	    ret = key_monitor_com();

#if defined (SUPPORT_VMX) || defined (SUPPORT_VMX_STD)
#ifdef NEW_SELF_TEST_UART_ENABLE
		if(ret == 3)
			ap_send_msg(CTRL_MSG_SUBTYPE_CMD_SELFTEST_UART_MSG, 0, TRUE);
#endif
#endif
		if(ret == 1 || ret==2)
		{
			if(ret == 1)
#ifdef UPGRADE_HOST_MONITOR			
				ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPGRADE, 0, TRUE);
#else
				;
#endif
			else
				ap_send_msg(CTRL_MSG_SUBTYPE_CMD_UPGRADE_SLAVE, 0, TRUE);
		}
#endif
#endif
		if(g_key_task_get_key && key_get_key(&key_struct, 1)
#ifdef CI_PLUS_SUPPORT
			&& (!app_disable_while_ci_upgrade)
#endif
		)
		{
#ifdef DUMP_KEY_CODE
            if(PAN_KEY_PRESSED== key_struct.state)
            {
                libc_printf("key = 0x%08x\n", key_struct.code);
            }
//            else 
//            {
//                libc_printf("press key = 0x%x\n", key_struct.code);
//            }
            continue;
#endif
			msg_code = scan_code_to_msg_code(&key_struct);
#ifdef _INVW_JUICE
#if 1 // ndef NDEBUG
	  {
	  static int kcnt = 0;
	  if (key_struct.state)
	    {
	      kcnt++;
	      printf(" ++++ %s: key = (%01X %01X %02X %04X) count = %3d\n",
		     __FUNCTION__,
		     key_struct.type,
		     key_struct.state,
		     key_struct.count,
		     SET_IRCODE(key_struct.code),
		     kcnt);
	    }
	  }
#endif
#endif
            if (m_pfn_key_notify)
            {
                m_pfn_key_notify(msg_code);
            }
			ap_send_msg(CTRL_MSG_SUBTYPE_KEY, msg_code, FALSE);
		}

        key_check_picture_status();

	#if (defined(EWS_FUNCTION))
	if(STOP_EWS_CC_STAT == get_ann_swtich_status())
	{
		ap_send_msg(CTRL_MSG_SUBTYPE_CMD_ANSWTICH_PRECHAN, 0, TRUE);	
	}
	#endif

#ifdef SFU_TEST_SUPPORT
//        extern volatile BOOL g_b_is_open_sfu;
//        if((!g_b_is_open_sfu)||(!SFUTestingIsTurnOn()))
        if( ! SFUTestingIsTurnOn() )
#endif
        {
            key_check_signal_status();
      //      #ifdef SUPPORT_CAS9
       #if defined( SUPPORT_CAS9) ||defined (SUPPORT_CAS7)
                key_check_mmi();
            #endif
        }

#ifdef DVR_PVR_SUPPORT		
		pvr_monitor_task();
#endif
#ifndef _BUILD_OTA_E_
#ifdef CI_SLOT_DYNAMIC_DETECT
        key_check_ca_prog(g_cam_pmt_ok_flag);
#endif
#endif

#ifdef GPIO_RGB_YUV_SWITCH
        if (system_state == SYS_STATE_NORMAL)
        {
            if (g_rgb_yuv_changed)
                continue;
            UINT8 rgb_yuv_sw = sys_get_rgb_yuv_switch();
            if (m_rgb_yuv_changing == 0)
            {
                if (g_rgb_yuv_switch != rgb_yuv_sw)
                {
                    m_rgb_yuv_changing = 1;
                }
            }
            else
            {
                m_rgb_yuv_changing = 0;
                if (g_rgb_yuv_switch != rgb_yuv_sw)
                {
                    g_rgb_yuv_switch = rgb_yuv_sw;
                    g_rgb_yuv_changed = 1;
            		ap_send_msg(CTRL_MSG_SUBTYPE_CMD_TVSAT_SWITCH, rgb_yuv_sw, FALSE);
                }
            }
        }
#endif

    {
        BoardCfg* cfg = get_board_cfg();
    	if( cfg && cfg->fp_standby_key )
    	{
            if( chip_gpio_get(cfg->fp_standby_key) )//the standby key is being pressed.
            {
                DELAY_MS(50);
                if( chip_gpio_get(cfg->fp_standby_key) )//the standby key is still being pressed.
                {
                	UINT32 hkey1 = INVALID_HK;
                	ap_vk_to_hk(0,V_KEY_POWER,&hkey1);	
                 	ap_send_msg(CTRL_MSG_SUBTYPE_KEY, hkey1, FALSE);
                }
            }
    	}
    }

#ifdef AUTOMATIC_STANDBY
    automatic_standby_loop();
#endif
	}//while(1)
}

//-----------------------------------------------------------------------------
// FUNCTION:    UIKeyInit:
//
// DESCRIPTION: init the keyboard devices(including frontpanel and remote controller) hardware
//
// RETURN:      True	Successful
//              False	Error when init the hardware
//
// NOTES:       
//
//-----------------------------------------------------------------------------
UINT8 key_Init()
{	
	OSAL_T_CTSK		t_ctsk;
	INT32	retVal;
	UINT32	i;

//	ir_key_map= &ir_key_maps[0];

//	for(i=0;i<SUPPORT_IR_NUM;i++)
//	{
//		if(ir_key_maps[i].irp_moudle == SYS_IRP_MOUDLE)
//		{
//			ir_key_map = &ir_key_maps[i];
//			break;
//		}
//	}
	

	t_ctsk.stksz	= 		INPUT_TASK_STACKSIZE * 2;
	t_ctsk.quantum	= 	INPUT_TASK_QUANTUM;
	t_ctsk.itskpri	= 		INPUT_TASK_PRIORITY;
	t_ctsk.name[0]	= 'K';
	t_ctsk.name[1]	= 'E';
	t_ctsk.name[2]	= 'Y';
	t_ctsk.task = (FP)key_task;
	INPUT_TASK_ID = osal_task_create(&t_ctsk);
	if(INPUT_TASK_ID==OSAL_INVALID_ID)
		return FALSE;

 	//rcu_fp_type.rcu_sw_pos = sys_data_get()->rcupos;   
	return TRUE;
}


UINT8   led_display_data[10];
UINT8   led_display_flag = 0;
UINT8   led_data_len;
UINT8   lock_status;
UINT8 	lock_status2;
UINT8   standby_status;
/* 0 - Normal, write both to LED and buf
   1 - write to LED only
   2 - write to buf only
*/

void key_pan_display(char *data, UINT32 len)
{
	UINT8 str[10];
	INT32 idx;
	if(led_display_flag == 0 || led_display_flag==1)
	{
		str[0] = data[0];
		idx = 1;
		str[idx++] = data[1];
		str[idx++] = data[2];
		str[idx++] = data[3];
		if(len == 5)
			str[idx++] = data[4];
			
		
		pan_display(g_pan_dev,str,idx);
	}

	if(led_display_flag == 0 || led_display_flag==2)
	{
		MEMCPY(led_display_data,data,len);
		led_display_data[len] = '\0';
	}
}

void key_pan_display_channel(UINT16 channel)
{
	UINT32 prog_num;
	char program[6];
	P_NODE p_node;
	T_NODE t_node;
#if (AOV_CHANGE_GROUP_ENABLE == SYS_FUNC_OFF)//ChengYu@20131014, disable change group function
	UINT8 group_index;
#endif

    if (g_pan_dev == NULL)
        return;

        UINT8 frontend_kind=0;
        frontend_kind = get_combo_config_frontend();
	prog_num = channel+1;

	get_prog_at(channel, &p_node);
	get_tp_by_id(p_node.tp_id, &t_node);

#if (AOV_CHANGE_GROUP_ENABLE == SYS_FUNC_OFF)//ChengYu@20131014, disable change group function
	group_index=sys_data_get_cur_group_index();
	if(group_index != 0)
	{
		sys_data_change_group(0);
		prog_num = get_prog_pos(p_node.prog_id)+1;
		sys_data_change_group(group_index);
	}
#endif

#if 0
#ifdef _LCN_ENABLE_     
    if(sys_data_get_cur_group_sat_id() == get_frontend_satid(FRONTEND_TYPE_T, 1) && sys_data_get_LCN()) 
    {
        if(g_pan_dev->led_num == 3)
            sprintf(program,"%02d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x07)+1);
        else
            sprintf(program,"%02d%01d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x1f)>>3, (p_node.prog_number & 0x07)+1);        
    }

    else if(/*sys_data_get_cur_group_index() == get_frontend_satid(FRONTEND_TYPE_T, 0) &&*/ sys_data_get_LCN())
    {
        if(g_pan_dev->led_num == 3)
    	    sprintf(program,"%03d",p_node.LCN);
        else
    	    sprintf(program,"%04d",p_node.LCN);        
    }   
    else
#endif           
    {
	    if(g_pan_dev->led_num == 3)
		    sprintf(program,"%03d",prog_num);
	    else
		    sprintf(program,"%04d",prog_num);
    }
#endif
#ifdef _LCN_ENABLE_
    if(frontend_kind==2)
    {
        //it's two different kind frontend
        if(sys_data_get_cur_group_sat_id() == get_frontend_satid(FRONTEND_TYPE_T, 1) && sys_data_get_LCN()) 
        {
            if(g_pan_dev->led_num == 3)
                sprintf(program,"%02d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x07)+1);
            else
                sprintf(program,"%02d%01d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x1f)>>3, (p_node.prog_number & 0x07)+1);        
        }

        else if(sys_data_get_cur_group_sat_id() == get_frontend_satid(FRONTEND_TYPE_T, 0) && sys_data_get_LCN())
        {
            if(g_pan_dev->led_num == 3)
        	    sprintf(program,"%03d",p_node.LCN);
            else
        	    sprintf(program,"%04d",p_node.LCN);        
        }
        else
        {
            if(g_pan_dev->led_num == 3)
		    sprintf(program,"%03d",prog_num);
	    else
		    sprintf(program,"%04d",prog_num);
        }
    }
    else if(frontend_kind==1)
    {
        //only one kind frontend
        //this is ISDBT
        if(check_frontend_type(FRONTEND_TYPE_T, 1) && sys_data_get_LCN())  
        {
            if(g_pan_dev->led_num == 3)
                sprintf(program,"%02d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x07)+1);
            else
                sprintf(program,"%02d:%01d%1d", t_node.remote_control_key_id, (p_node.prog_number & 0x1f)>>3, (p_node.prog_number & 0x07)+1);        
        }
        //this is DVBT
        else if(check_frontend_type(FRONTEND_TYPE_T, 0) && sys_data_get_LCN())
        {
            if(g_pan_dev->led_num == 3)
                sprintf(program,"%03d",p_node.LCN);
            else
                sprintf(program,"%04d",p_node.LCN);   
        }
        else
        {
            if(g_pan_dev->led_num == 3)
                sprintf(program,"%03d",prog_num);
            else
                sprintf(program,"%04d",prog_num);
        }
           
    }
    else
#endif                
    {
        if(g_pan_dev->led_num == 3)
            sprintf(program,"%03d",prog_num);
        else
            sprintf(program,"%04d",prog_num);
    }
        
    
key_pan_display(program, g_pan_dev->led_num+1);
}

void key_pan_display_lock(UINT8 	flag)
{
	UINT8	uChannel[4];
    UINT8   backup_show_state;
	if(flag != lock_status)
	{
		uChannel[0] = 27;
		uChannel[1] = PAN_ESC_CMD_LBD;
		uChannel[2] = PAN_ESC_CMD_LBD_LOCK ;
		if(flag)
 			uChannel[3] = PAN_ESC_CMD_LBD_ON;
 		else
 			uChannel[3] = PAN_ESC_CMD_LBD_OFF;
        backup_show_state = led_display_flag;
        led_display_flag  = 1;
        key_pan_display(uChannel, 4);
        led_display_flag = backup_show_state;
		lock_status = flag;
	}	
}

void key_pan_display_lock2(UINT8 	flag)
{
	UINT8 uChannel[4];
	UINT8 postion=3; // for second tuner lock led.
    UINT8   backup_show_state;
	if(flag != lock_status2)
	{
		uChannel[0] = 27;
		uChannel[1] = PAN_ESC_CMD_LBD;
		uChannel[2] = PAN_ESC_CMD_LBD_LOCK ;
		if(flag)
 			uChannel[3] = PAN_ESC_CMD_LBD_ON|(postion<<4);
 		else
 			uChannel[3] = PAN_ESC_CMD_LBD_OFF|(postion<<4);
        backup_show_state = led_display_flag;
        led_display_flag  = 1;        
 		key_pan_display(uChannel, 4);
        led_display_flag = backup_show_state;
		lock_status2 = flag;
	}	
}


void key_pan_display_standby(UINT8 	flag)
{
	UINT8	uChannel[4];

	if(flag != standby_status)
	{
		uChannel[0] = 27;
		uChannel[1] = PAN_ESC_CMD_LBD;
		uChannel[2] = PAN_ESC_CMD_LBD_FUNCA;
		if(flag)
 			uChannel[3] = PAN_ESC_CMD_LBD_ON;
 		else
 			uChannel[3] = PAN_ESC_CMD_LBD_OFF;
 		key_pan_display(uChannel, 4);
		standby_status = flag;
	}
}

void key_pan_display_power(UINT8 	flag)
{
	UINT8	uChannel[4];

	//if(flag != standby_status)
	{
		uChannel[0] = 27;
		uChannel[1] = PAN_ESC_CMD_LBD;
		uChannel[2] = PAN_ESC_CMD_LBD_POWER;
		if(flag)
 			uChannel[3] = PAN_ESC_CMD_LBD_ON;
 		else
 			uChannel[3] = PAN_ESC_CMD_LBD_OFF;
 		key_pan_display(uChannel, 4);
		//standby_status = flag;
	}
}


void key_pan_set_key_table(IR_Key_Map_t* key_tab)
{
	UINT32	address;
	UINT32		i;

/*	
	#define SUPPORT_IR_NUM 0
	
	for(i=0;i<SUPPORT_IR_NUM;i++)
	{
		if(key_tab[i].irp_moudle == SYS_IRP_MOUDLE)
		{
			break;
		}
	}
*/
	i = 0;
	
	//ASSERT(i < SUPPORT_IR_NUM);
	
	address = key_tab[i].irkey_addr;//LV_IR008_Address[rcu_sw_pos];
	switch(key_tab->irp_protocal)
	{
		case IRP_NEC:
			key_address = address << 16;
			key_address_mask = IR_NEC_KEY_MASK;
			break;
		case IRP_ITT:
		case IRP_NRC17:
		case IRP_SHARP:
		case IRP_SIRC:
		case IRP_RC5:
		case IRP_RC6:
		default:
			return;//hwIrKey = ((0xFF - address) << 24) + (address << 16) + ((0xFF - code) << 8) + code;
	}
}

#ifdef WATCH_DOG_SUPPORT
static OSAL_ID DOG_TASK_ID;
static void dog_task()
{
    dog_m3327e_attach(1);
    dog_mode_set(0, DOG_MODE_WATCHDOG, 60000000, NULL);
    while(1)
    {
        dog_set_time(0, 0);
        osal_task_sleep(100);
    }
}
#endif

UINT8 dog_init()
{   
#ifdef WATCH_DOG_SUPPORT
    OSAL_T_CTSK     t_ctsk;
    INT32   retVal;
    UINT32  i;

    t_ctsk.stksz    =       INPUT_TASK_STACKSIZE;
    t_ctsk.quantum  =   INPUT_TASK_QUANTUM;
    t_ctsk.itskpri  =       INPUT_TASK_PRIORITY;
    t_ctsk.name[0]  = 'D';
    t_ctsk.name[1]  = 'O';
    t_ctsk.name[2]  = 'G';
    t_ctsk.task = (FP)dog_task;
    DOG_TASK_ID = osal_task_create(&t_ctsk);
    if(DOG_TASK_ID == OSAL_INVALID_ID)
        return FALSE;
#else
    dog_stop(0);
#endif
    return TRUE;
}

